package cn.yitun.chat.yitunserverimapicore.business.group.service.impl;

import cn.yitun.chat.yituncommonmessage.ExceptionEnum;
import cn.yitun.chat.yituncommonmessage.Info;
import cn.yitun.chat.yituncommonutil.YitunCollectionUtil;
import cn.yitun.chat.yitunservercommonlib.converter.dto2vo.group.GroupInviteApplyDto2VoConverter;
import cn.yitun.chat.yitunservercommonlib.dataentity.dto.group.GroupInviteApplyDto;
import cn.yitun.chat.yitunservercommonlib.dataentity.vo.group.GroupInviteApplyVo;
import cn.yitun.chat.yitunservercommonlib.dataentity.vo.group.GroupMemberVo;
import cn.yitun.chat.yitunservercommonlib.dataentity.vo.group.GroupSettingVo;
import cn.yitun.chat.yitunservercommonlib.enums.groupChat.GroupInviteSettingTypeEnums;
import cn.yitun.chat.yitunservercommonlib.enums.groupChat.GroupJoinVerifySettingTypeEnums;
import cn.yitun.chat.yitunservercommonlib.enums.groupChat.GroupMemberPositionEnums;
import cn.yitun.chat.yitunservercommonlib.enums.userChat.UserRequestTypeEnums;
import cn.yitun.chat.yitunservercommonlib.util.R;
import cn.yitun.chat.yitunservercommonlib.util.codec.IdGen;
import cn.yitun.chat.yitunserverimapicore.business.group.service.GroupInviteService;
import cn.yitun.chat.yitunserverimbase.dao.group.GroupInviteApplyDao;
import cn.yitun.chat.yitunserverimbase.dao.group.GroupMemberDao;
import cn.yitun.chat.yitunserverimcore.general.main.biz.group.manager.*;
import cn.yitun.chat.yitunserverimcore.general.main.push.group.GroupInvitePush;
import cn.yitun.chat.yitunserverimcore.general.main.push.group.GroupMemberPush;
import cn.yitun.chat.yitunserverimcore.general.main.push.group.GroupRelationPush;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 
 * Date 2019-01-23 22:01:34<br>
 * Description
 * 
 * @author yitun
 * @since 1.0.0
 */
@Service
@Transactional
public class GroupInviteServiceImpl implements GroupInviteService {

	@Resource
	private GroupMemberDao groupMemberDAO;
	@Resource
	private GroupInviteApplyDao groupInviteApplyDAO;
	@Resource
	private GroupManager groupManager;
	@Resource
	private GroupMemberManager groupMemberManager;
	@Resource
	private GroupRelationManager groupRelationManager;
	@Resource
	private GroupCategoryManager groupCategoryManager;
	@Resource
	private GroupJoinSettingManager groupJoinSettingManager;
	@Resource
	private GroupInvitePush groupInvitePush;
	@Resource
	private GroupMemberPush groupMemberPush;
	@Resource
	private GroupRelationPush groupRelationPush;

	/**
	 * 
	 * Date 2019-01-26 23:23:05<br>
	 * Description 邀请加入群
	 * 
	 * @author yitun
	 * @param inviterUserId
	 * @param groupId
	 * @param userIds
	 * @return
	 * @since 1.0.0
	 */
	public Info invite(Long inviterUserId, Long groupId, List<Long> userIds) {

		Info info = new Info();

		if (null == groupId || null == userIds || userIds.isEmpty()) {
			info.addWarning(ExceptionEnum.LOSE_FILED);
			return info;
		}

		if (userIds.size() > 1000) {
			info.addWarning(ExceptionEnum.REQUEST_PARAM_ERROR);
			return info;
		}

		boolean hasGroup = groupManager.has(groupId);

		if (!hasGroup) {
			info.addWarning(ExceptionEnum.REQUEST_PARAM_ERROR);
			return info;
		}

		String inviterUserPosition = groupMemberManager.getPosition(groupId, inviterUserId);

		Long groupOwnerUserId = groupMemberManager.getGroupOwnerUserId(groupId);

		// 发起邀请人的角色
		boolean inviterIsAdmin = groupMemberManager.isAdmin(inviterUserPosition);
		boolean inviterIsOwner = groupMemberManager.isOwner(inviterUserPosition);
		boolean inviterIsNormal = groupMemberManager.isNormal(inviterUserPosition);

		// 不是任何一个角色，说明不在群中，不可以邀请人加入
		if (!inviterIsAdmin && !inviterIsOwner && !inviterIsNormal) {
			info.addWarning(ExceptionEnum.USER_HAVE_NO_PERMISSIONS);
			return info;
		}

		// 先获取安全设置
		GroupSettingVo setting = groupJoinSettingManager.getByGroupId(groupId);
		String verifyType = setting.getInviteType();
		String joinType = setting.getJoinType();

		String inviteeHandleType = UserRequestTypeEnums.HANDLE_TYPE_UNTREATED.getType();

		String verifyHandleType = UserRequestTypeEnums.HANDLE_TYPE_UNTREATED.getType();
		Long verifyUserId = 0l;
		String verifyUserPosition = "0";

		// 防止被邀请的用户已经加入群了
		userIds = filterExisted(groupId, userIds);

		if (GroupJoinVerifySettingTypeEnums.VERIFY_TYPE_NEVER.getType().equals(verifyType)
				|| GroupJoinVerifySettingTypeEnums.VERIFY_TYPE_NEVER.getType().equals(joinType)) {
			// 不允许邀请加入（群主可以邀请）
			LocalDateTime verifyHandleDateTime = null;
			if (inviterIsOwner) {
				// 群主邀请，默认通过，只需用户自己通用即可
				verifyHandleType = UserRequestTypeEnums.HANDLE_TYPE_ACCEPT.getType();
				verifyHandleDateTime = LocalDateTime.now();
				verifyUserId = inviterUserId;
				verifyUserPosition = inviterUserPosition;

				for (Long inviteeUserId : userIds) {

					GroupInviteApplyDto apply = new GroupInviteApplyDto();
					apply.setGroupId(groupId);
					apply.setInviterUserId(inviterUserId);
					apply.setInviterUserPosition(inviterUserPosition);

					apply.setInviteeUserId(inviteeUserId);
					apply.setInviteeHandleType(inviteeHandleType);

					apply.setVerifyType(verifyType);
					apply.setVerifyHandleType(verifyHandleType);
					apply.setVerifyUserId(verifyUserId);
					apply.setVerifyUserPosition(verifyUserPosition);
					apply.setInviterMessage("");
					groupInviteApplyDAO.save(apply);

					// TODO推送给被邀请的人，进行同意/拒绝处理
					groupInvitePush.pushInvite(IdGen.getNumber(), groupId, apply.getId(), inviteeUserId);
				}

			} else {
				info.addWarning(ExceptionEnum.SOCK_GROUP_INVITE_NOT_ALLOW);
			}
		} else if (GroupInviteSettingTypeEnums.INVITE_TYPE_ANY.getType().equals(verifyType)) {

			// 任何人都可以邀请加入
			verifyHandleType = UserRequestTypeEnums.HANDLE_TYPE_ACCEPT.getType();

			if (inviterIsAdmin || inviterIsOwner) {
				// 如果是管理员或者群主邀请，默认已处理
				verifyUserId = inviterUserId;
				verifyUserPosition = inviterUserPosition;
			} else {
				verifyUserId = groupOwnerUserId;
				verifyUserPosition = GroupMemberPositionEnums.POSITION_OWNER.getType();
			}

			for (Long inviteeUserId : userIds) {
				GroupInviteApplyDto apply = new GroupInviteApplyDto();

				apply.setGroupId(groupId);

				apply.setInviterUserId(inviterUserId);
				apply.setInviterUserPosition(inviterUserPosition);

				apply.setInviteeUserId(inviteeUserId);
				apply.setInviteeHandleType(inviteeHandleType);

				apply.setInviteeHandleType(inviteeHandleType);
				// apply.setInviterHandleDateTime(LocalDateTime.now());

				apply.setVerifyType(verifyType);
				apply.setVerifyHandleType(verifyHandleType);
				apply.setVerifyUserId(verifyUserId);
				apply.setVerifyUserPosition(verifyUserPosition);
				apply.setInviterMessage("");

				groupInviteApplyDAO.save(apply);

				if (UserRequestTypeEnums.HANDLE_TYPE_ACCEPT.getType().equals(verifyHandleType)) {
					// TODO推送给被邀请的人，进行同意/拒绝处理
					groupInvitePush.pushInvite(IdGen.getNumber(), groupId, apply.getId(), inviteeUserId);
				}
			}
		} else if (GroupInviteSettingTypeEnums.INVITE_TYPE_ADMIN.getType().equals(verifyType)) {

			// 管理员或者群主才可以邀请

			verifyHandleType = UserRequestTypeEnums.HANDLE_TYPE_ACCEPT.getType();

			if (inviterIsAdmin || inviterIsOwner) {
				verifyUserId = inviterUserId;
				verifyUserPosition = inviterUserPosition;

				for (Long inviteeUserId : userIds) {
					GroupInviteApplyDto apply = new GroupInviteApplyDto();

					apply.setGroupId(groupId);

					apply.setInviterUserId(inviterUserId);
					apply.setInviterUserPosition(inviterUserPosition);

					apply.setInviteeUserId(inviteeUserId);
					apply.setInviteeHandleType(inviteeHandleType);

					apply.setVerifyType(verifyType);

					apply.setVerifyHandleType(verifyHandleType);
					apply.setVerifyUserId(verifyUserId);
					apply.setVerifyUserPosition(verifyUserPosition);
					apply.setInviterMessage("");

					groupInviteApplyDAO.save(apply);

					if (UserRequestTypeEnums.HANDLE_TYPE_ACCEPT.getType().equals(verifyHandleType)) {
						// TODO推送给被邀请的人，进行同意/拒绝处理
						groupInvitePush.pushInvite(IdGen.getNumber(), groupId, apply.getId(), inviteeUserId);
					}
				}
			} else {
				info.addWarning(ExceptionEnum.SOCK_GROUP_INVITE_NO_PERMISSION);
			}
		} else if (GroupInviteSettingTypeEnums.INVITE_TYPE_AUTH.getType().equals(verifyType)) {

			// 管理员或者群主验证才可以

			LocalDateTime verifyHandleDateTime = null;

			if (inviterIsAdmin || inviterIsOwner) {
				// 群主或者管理员自己邀请默认已经处理
				verifyHandleType = UserRequestTypeEnums.HANDLE_TYPE_ACCEPT.getType();
				verifyHandleDateTime = LocalDateTime.now();
				verifyUserId = inviterUserId;
				verifyUserPosition = inviterUserPosition;

			}
			List<Long> adminAndOwnerUserIds = groupMemberManager.getGroupAdminAndOwnerUserIdList(groupId);
			for (Long inviteeUserId : userIds) {
				GroupInviteApplyDto apply = new GroupInviteApplyDto();

				apply.setGroupId(groupId);

				apply.setInviterUserId(inviterUserId);
				apply.setInviterUserPosition(inviterUserPosition);

				apply.setInviteeUserId(inviteeUserId);
				apply.setInviteeHandleType(inviteeHandleType);

				apply.setVerifyType(verifyType);
				apply.setVerifyHandleType(verifyHandleType);
				apply.setVerifyUserId(verifyUserId);

				apply.setVerifyUserPosition(verifyUserPosition);
				apply.setInviterMessage(""); //邀请的信息

				apply.setCreateBy(inviterUserId);
				apply.setUpdateBy(inviterUserId);

				groupInviteApplyDAO.save(apply);

				if (UserRequestTypeEnums.HANDLE_TYPE_ACCEPT.getType().equals(verifyHandleType)) {
					// TODO推送给被邀请的人，进行同意/拒绝处理
					groupInvitePush.pushInvite(IdGen.getNumber(), groupId, apply.getId(), inviteeUserId);
				} else {
					groupInvitePush.pushInviteApply(IdGen.getNumber(), groupId, apply.getId(), adminAndOwnerUserIds);
				}
			}
		}
		return info;
	}

	/**
	 * Date 2019-01-26 23:49:54<br>
	 * Description 管理员或者群主验证处理邀请
	 * @param verifyHandleUserId
	 * @param inviteApplyIds
	 * @param verifyHandleType
	 * @return
	 * @since 1.0.0
	 */
	public Info verifyHandle(Long verifyHandleUserId, List<Long> inviteApplyIds, String verifyHandleType) {
		Info info = new Info();
		if (YitunCollectionUtil.isNotEmpty(inviteApplyIds)) {
			for (Long inviteApplyId : inviteApplyIds) {
				GroupInviteApplyVo inviteApply = groupInviteApplyDAO.getVO(inviteApplyId);

				if (null != inviteApply
						&& UserRequestTypeEnums.HANDLE_TYPE_UNTREATED.getType().equals(inviteApply.getVerifyHandleType())) {
					Long groupId = inviteApply.getGroupId();

					String verifyHandleUserPosition = groupMemberManager.getPosition(groupId, verifyHandleUserId);

					boolean isAdmin = groupMemberManager.isAdmin(verifyHandleUserPosition);
					boolean isOwner = groupMemberManager.isOwner(verifyHandleUserPosition);
					if (isAdmin || isOwner) {

						inviteApply.setVerifyHandleType(verifyHandleType);
						inviteApply.setVerifyUserPosition(verifyHandleUserPosition);
						inviteApply.setVerifyUserId(verifyHandleUserId);
						groupInviteApplyDAO.update(GroupInviteApplyDto2VoConverter.INSTANCE.vo2dto(inviteApply));
						// TODO 推送管理员已经处理结过
						Long inviteeUserId = inviteApply.getInviteeUserId();
						if (UserRequestTypeEnums.HANDLE_TYPE_ACCEPT.getType().equals(verifyHandleType)) {
							// TODO推送给被邀请的人，进行同意/拒绝处理
							groupInvitePush.pushInvite(IdGen.getNumber(), groupId, inviteApplyId, inviteeUserId);
						}
					} else {
						info.addWarning(ExceptionEnum.SOCK_GROUP_INVITE_NO_PERMISSION);
					}
				} else {
					info.addWarning(ExceptionEnum.SOCK_GROUP_INVITE_HAVE_DONE);
				}
			}
		}
		return info;
	}

	/**
	 * Date 2019-01-26 23:55:25<br>
	 * Description 用户处理被邀请加入群，同意/拒绝
	 * @author yitun
	 * @param inviteeUserId
	 * @param inviteApplyId
	 * @param inviteeHandleType
	 * @return
	 * @since 1.0.0
	 */
	@Transactional
	public Info inviteeHandle(Long inviteeUserId, Long inviteApplyId, String inviteeHandleType) {
		Info info = new Info();
		GroupInviteApplyVo inviteApply = groupInviteApplyDAO.getVO(inviteApplyId);
		if (null != inviteApply && inviteeUserId.equals(inviteApply.getInviteeUserId())) {

			if (UserRequestTypeEnums.HANDLE_TYPE_UNTREATED.getType().equals(inviteApply.getInviteeHandleType())) {

				inviteApply.setInviteeHandleType(inviteeHandleType);
				groupInviteApplyDAO.update(GroupInviteApplyDto2VoConverter.INSTANCE.vo2dto(inviteApply));

				Long categoryId = groupCategoryManager.getOrCreateDefaultCategoryId(inviteeUserId);

                Long groupId = inviteApply.getGroupId();
				String remark = "";

				if (UserRequestTypeEnums.HANDLE_TYPE_ACCEPT.getType().equals(inviteeHandleType)) {
					if (!groupRelationManager.has(inviteeUserId, groupId)) {
						groupRelationManager.add(groupId, inviteeUserId, categoryId, remark);
					}
					if (!groupMemberManager.inGroup(groupId, inviteeUserId)) {
						groupMemberManager.add(groupId, inviteeUserId);
					}
					List<Long> userIds = groupMemberManager.getGroupMemberUserIdList(groupId);
					groupRelationPush.pushAdd(IdGen.getNumber(), groupId, inviteeUserId);
					groupMemberPush.pushAdd(groupId, inviteeUserId, userIds);
				} else {

				}
			}
		} else {
			info.addWarning(ExceptionEnum.LOSE_FILED);
		}
		return info;
	}

	/**
	 * 
	 * Date 2019-01-26 23:59:07<br>
	 * Description 过滤掉已经在群中的用户/或者尚未处理的请求
	 * 
	 * @author yitun
	 * @param groupId
	 * @param userIds
	 * @return
	 * @since 1.0.0
	 */
	private List<Long> filterExisted(Long groupId, List<Long> userIds) {

		List<GroupInviteApplyVo> applys = groupInviteApplyDAO.getUntreatedListByInviteeUserIds(
				R.param("groupId", groupId)
				.put("userIds", userIds)
				.put("verifyHandleType", UserRequestTypeEnums.HANDLE_TYPE_UNTREATED.getType())
				.put("inviteeHandleType", UserRequestTypeEnums.HANDLE_TYPE_UNTREATED.getType())
		);

		List<Long> list = new ArrayList<>();
		List<GroupMemberVo> members = groupMemberDAO.listVO(
				R.param("groupId", groupId));
		int size = members.size() + applys.size();
		Map<Long, Long> map = new HashMap<>(size);
		for (GroupMemberVo m : members) {
			map.put(m.getUserId(), m.getUserId());
		}

		for (GroupInviteApplyVo m : applys) {
			map.put(m.getInviteeUserId(), m.getInviteeUserId());
		}

		for (Long id : userIds) {
			if (!map.containsKey(id)) {
				list.add(id);
			}
		}
		return list;
	}
}
